﻿using System.Collections.Generic;
using UnityEngine;
using System.IO;

namespace TinyAsset
{
    public class HotUpdateManager : MonoSingleton<HotUpdateManager>
    {
        Manifest m_LocalManifest;
        Manifest m_RemoteManifest;

        string m_PlatformName;
        string m_BaseDownloadUrl;
        string m_RemoteResVersionStr;

        public override void Awaking()
        {
            m_PlatformName = AssetBundleUtility.GetPlatformName();
        }

        public void SetBaseDownloadUrl(string url)
        {
            m_BaseDownloadUrl = url;
        }

        public void SetLocalManifest(Manifest manifest)
        {
            m_LocalManifest = manifest;
        }

        public UnityHttpRequest RequestRemoteManifest(string fileName)
        {
            var req = UnityHttpClient.Instance.Get(Path.Combine(m_BaseDownloadUrl, m_PlatformName, fileName));
            req.onCompleted += (r) => {
                if (req.response.isSuccessful)
                {
                    using (MemoryStream stream = new MemoryStream(req.response.data))
                    {
                        using (BinaryReader reader = new BinaryReader(stream))
                        {
                            m_RemoteManifest = new Manifest();
                            m_RemoteManifest.Deserialize(reader);
                            m_RemoteResVersionStr = m_RemoteManifest.resVersion.ToString();
                        }
                    }
                }
            };
            return req;
        }

        public void SaveRemoteManifest(string fileName, bool useImmediately)
        {
            if (m_RemoteManifest != null)
            {
                string path = Path.Combine(Application.persistentDataPath, fileName);
                using (FileStream fileStream = File.Open(path, FileMode.OpenOrCreate, FileAccess.Write))
                {
                    using (BinaryWriter writer = new BinaryWriter(fileStream))
                    {
                        m_RemoteManifest.Serialize(writer);
                    }
                }
                if (useImmediately)
                    ResourceManager.Instance.SetCurrentManifest(m_RemoteManifest);
            }
        }

        public List<AbstractFileEntity> CheckUpdate(string groupName)
        {
            List<AbstractFileEntity> fileEntities = m_RemoteManifest.GetFileEntitiesByGroupName(groupName);
            List<AbstractFileEntity> result = new List<AbstractFileEntity>();
            foreach (var item in fileEntities)
            {
                if (IsNewest(item))
                    result.Add(item);
            }
            return result;
        }

        public List<AbstractFileEntity> CheckUpdateAll()
        {
            List<AbstractFileEntity> result = new List<AbstractFileEntity>();
            foreach (var item in m_RemoteManifest.fileEntityGroups)
            {
                var fileEntities = CheckUpdate(item.name);
                result.AddRange(fileEntities);
            }
            return result;
        }

        public UnityHttpRequest Download(AbstractFileEntity fileEntity)
        {
            var origin = Path.Combine(m_BaseDownloadUrl, m_PlatformName, m_RemoteResVersionStr, fileEntity.type == 0 ? null : AssetBundleUtility.kAssetBundle, fileEntity.name);
            var destination = Path.Combine(Application.persistentDataPath,fileEntity.type == 0 ? null : AssetBundleUtility.kAssetBundle, fileEntity.name);
            return UnityHttpClient.Instance.Download(origin, destination);
        }

        public List<UnityHttpRequest> Download(List<AbstractFileEntity> fileEntities)
        {
            List<UnityHttpRequest> requests = new List<UnityHttpRequest>();
            foreach (var item in fileEntities)
                requests.Add(Download(item));
            return requests;
        }

        public List<UnityHttpRequest> DownloadAll()
        {
            List<UnityHttpRequest> requests = new List<UnityHttpRequest>();
            foreach (var item in m_RemoteManifest.fileEntityGroups)
            {
                var fileEntities = CheckUpdate(item.name);
                foreach (var fileEntity in fileEntities)
                    requests.Add(Download(fileEntity));
            }
            return requests;
        }

        bool IsNewest(AbstractFileEntity fileEntity)
        {
            if (m_LocalManifest == null)
                return true;
            var local = m_LocalManifest.GetFileEntity(fileEntity.name);
            if (local != null && local.hash == fileEntity.hash)
            {
                if (local.location != 0)
                {
                    var filePath = Path.Combine(Application.persistentDataPath,local.type == 0 ? null : AssetBundleUtility.kAssetBundle, local.name);
                    if (!File.Exists(filePath))
                        return true;
                    var hash = FileHelper.GetFileMd5(filePath);
                    if (hash == fileEntity.hash)
                        return false;
                }
                return false;
            }
            return true;
        }
    }
}